<?php

require_once 'ActionFramework/database.php';

interface ILanguageTandemDatabase {
	/**
	 * Returns whether there exists a user with this email address
	 */
	public function is_email_known($email);
	
	/**
	 * Creates a new signup user, and returns a unique secret. 
	 */
	public function create_new_signup_user($name, $email) ;
	
	/**
	 * Returns whether the signup secret exists
	 */
	public function signup_secret_exists($secret);
	
	/**
	 * Return the email and name of a signup user
	 */
	public function get_signup_user_data($secret);
	
	/**
	 * Remove the temporary signup user
	 */
	public function remove_signup_user($secret);
	
	public function create_login_by_url_secret(GeneralUser $user);
	
	public function get_login_by_url_user($secret);
	
	/**
	 * Update the "last login" field to the current time
	 */
	public function flag_login(GeneralUser $user);	
	
	/**
	 * Create a regular user in the database
	 */
	public function create_user($user_data);
	
	/**
	 * Get the User with the id given from the database
	 */
	public function get_user_by_id($user_id);
	
	/**
	 * Get the User with the emailaddress given from the database
	 */
	public function get_user_by_email($email);
	
	/**
	 * get all regular users
	 */
	public function get_all_users();
	
	/**
	 * Get all emailadresses of users (normal and admin) that are interested 
	 * in the newsletter.
	 */
	public function get_all_newsletter_addresses();
	
	/**
	 * Save the User data in the database with the current data of User.
	 */
	public function save_user(GeneralUser $user);
	
	/**
	 * Update the User data with data from the database (discard data in the User object)
	 */
	public function update_user(GeneralUser $user);
	
	public function reject(User $user, $rejected_user_id);

	public function unreject(User $user, $rejected_user_id);
	
	public function remove_user(GeneralUser $user);
	
	/**
	 * Creates a challenge and challenge_id, for secure login purposes.
	 * The challenge expires within an hour.
	 * 
	 * Returns: (challenge_id, challenge)
	 */
	public function create_challenge();
	
	/**
	 * Get the challenge that belongs to a challenge_id. If the challenge_id
	 * is unknown, return null. If found, the challenge is removed.
	 */
	public function get_challenge($challenge_id);
	
	public function log_message_sent(GeneralUser $from, GeneralUser $to);
	
	public function messages_sent_by_user_since(GeneralUser $user, Date $since);
	
	public function messages_sent_since(Date $since);
	
}


class LanguageTandemDatabase extends SQLDatabase implements ILanguageTandemDatabase {
	
	
	public function is_email_known($email) {
		$query = $this->link->prepare("
				SELECT email
				FROM {$this->t_prefix}general_users
				WHERE email=?
				LIMIT 0 , 1
		");
		$query->execute(array($email));
		$found = (boolean) $query->fetch();
		$query->closeCursor();		
		return $found;
	} 
	
	/**
	 * Creates a new signup user, and returns a unique secret
	 * (in fact signup_id [6 chars] + actual secret [20 chars])
	 */
	public function create_new_signup_user($name, $email) {
		// The secret returned is a generated secret + the auto increment, so that each code is guaranteed to be unique.
		$random = generate_random_string(20);
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}signup_users (
				secret , email , name , registration_time )
			VALUES (
				?, ?, ?, CURRENT_TIMESTAMP );
		");
		$query->execute(array($random, $email, $name));
		$query->closeCursor();
		
		return $this->create_secret($this->link->lastInsertId(), $random);
	}
	
	private function create_secret($id, $random) {
		return str_pad($id, 6, '0', STR_PAD_LEFT) . $random;
	}
	
	private function parse_secret($secret) {
		return array(
			intval(substr($secret, 0, 6)),
			substr($secret, 6, 26)
		);
	}
	
	/**
	 * Returns whether the signup secret exists
	 */
	public function signup_secret_exists($secret) {
		return (bool) $this->get_signup_user_data($secret);
	}
	
	/**
	 * Return the email and password of someone that stared the signup process
	 */
	public function get_signup_user_data($secret) {
		list($signup_id, $random) = $this->parse_secret($secret);			
		$query = $this->link->prepare("
				SELECT email, name
				FROM {$this->t_prefix}signup_users
				WHERE signup_id=? AND secret=?
				LIMIT 0 , 1
		");
		$query->execute(array($signup_id, $random));
		$row = $query->fetch();
		$query->closeCursor();		
		return $row;		
	}
	
	/**
	 * Remove the temporary account created while signing up
	 */
	public function remove_signup_user($secret) {
		list($signup_id, $random) = $this->parse_secret($secret);
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}signup_users
				WHERE signup_id=? AND secret=?
				LIMIT 1
		");
		$query->execute(array($signup_id, $random));
		$query->closeCursor();		
	}
	
	public function create_login_by_url_secret(GeneralUser $user) {
		$random = generate_random_string(20);
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}login_by_url (
				user_id, secret )
			VALUES (?, ?);
		");
		$query->execute(array($user->user_id, $random));
		$query->closeCursor();
		
		return $this->create_secret($this->link->lastInsertId(), $random);
	}
	
	public function get_login_by_url_user($secret) {
		list($index, $random) = $this->parse_secret($secret);	
		$query = $this->link->prepare("
				SELECT user_id
				FROM {$this->t_prefix}login_by_url
				WHERE id=? AND secret=?
				LIMIT 0 , 1
		");
		$query->execute(array($index, $random));
		$row = $query->fetch();
		$query->closeCursor();	
		if (!$row) {
			return null;
		}
		
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}login_by_url
				WHERE id=? AND secret=?
				LIMIT 1
		");
		$query->execute(array($index, $random));
		$query->closeCursor();	

		return $this->get_user_by_id($row['user_id']);
		
	}
	
	/**
	 * Create a regular user
	 */
	public function create_user($user_data) {
		// Remember that this user might miss attributes, which are not required because they have a default.
		$user = new User($user_data);
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}general_users (
				email , password , first_name, last_name , admin , newsletter)
			VALUES (
				?, ?, ?, ?, FALSE, ?);
		");
		$query->execute(array(
					$user->email, 
					$user->password, 
					$user->first_name, 
					$user->last_name,
					$user->newsletter,
		));
		$query->closeCursor();
		$user->user_id = $this->link->lastInsertId();
		
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}users (
				user_id , date_of_birth , gender , facebook, about_yourself , email_when_new_match , invisible, blocked )
			VALUES (
				?, ?, ?, ?, ?, ?, ?, FALSE);
		");
		$success = $query->execute(array(
					$user->user_id, 
					$user->date_of_birth->getDate(), // ISO format 
					$user->gender, 
					$user->facebook, 
					$user->about_yourself,
					$user->email_when_new_match,
					$user->invisible
		));
		if (!$success) {
			var_dump($query->errorInfo());
			throw new Exception("Query error");
		}
		$query->closeCursor();
		
		$this->save_languages($user);
		
		// Get a clean, full user (incl. signup date)
		return $this->get_user_by_id($user->user_id);
	}
	
	public function get_user_by_email($email) {
		return $this->get_user(array('field' => 'email', 'value' => $email));
	}
	
	public function get_user_by_id($user_id) {
		return $this->get_user(array('field' => 'user_id', 'value' => $user_id));
	}
	
	private function get_user($condition) {
		$query = $this->link->prepare("
				SELECT user_id, email , password , first_name, last_name , admin , newsletter, last_login
				FROM {$this->t_prefix}general_users
				WHERE {$condition['field']}=?
				LIMIT 0 , 1
		");
		$success = $query->execute(array($condition['value']));
		if (!$success) {
			echo 'A Database error occured. Sorry!';
			if (DEBUG) {
				echo $query->errorInfo();
			}
			die();
		}
		
		$general_user_row = $query->fetch();
		$query->closeCursor();
		
		if (!$general_user_row) {
			return null;
		}
		
		if ($general_user_row['last_login'] == '0000-00-00 00:00:00') {
			$general_user_row['last_login'] = new Date('1971-01-01 00:00:00');
		} else {
			$general_user_row['last_login'] = new Date($general_user_row['last_login']);
		}
		
		// Get all the things we need, and only the things we need
		$general_user_row = array_extract($general_user_row, r(new GeneralUser(array()))->get_attribute_names());
		
		if ($general_user_row['admin']) {
			return new Admin($general_user_row);
		}
		
		$user = new User($general_user_row);
		
		// Fetch other data
		$query = $this->link->prepare("
				SELECT date_of_birth , gender , facebook, about_yourself , email_when_new_match , invisible, signup_date, blocked
				FROM {$this->t_prefix}users
				WHERE user_id=?
				LIMIT 0 , 1
		");
		$query->execute(array($user->user_id));
		$row = $query->fetch();
		$query->closeCursor();	
		if (!$row) {
			throw new Exception("Database sql query error: no data returned after query (#83273) [ user id: {$user->user_id}]");
		}
		
		$user->update(array_extract($row, r(new User(array()))->get_attribute_names(), $only_if_present=true));
		$user->date_of_birth = new Date($user->date_of_birth);
		$user->signup_date = new Date($user->signup_date);
		
		
		// Known laguages
		$query = $this->link->prepare("
				SELECT language_code
				FROM {$this->t_prefix}known_languages
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$languages = array();
		while ($row = $query->fetch()) {
			$languages[] = $row['language_code'];
		}
		$query->closeCursor();	
		$user->known_languages = $languages;		
		
		
		// Unknown laguages
		$query = $this->link->prepare("
				SELECT language_code, level
				FROM {$this->t_prefix}unknown_languages
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$languages_and_levels = array();
		while ($row = $query->fetch()) {
			$languages_and_levels[] = array($row['language_code'], $row['level']);
		}
		$query->closeCursor();	
		$user->unknown_languages_and_levels = $languages_and_levels;	
		
		// Rejected partners
		$query = $this->link->prepare("
				SELECT rejected_user_id
				FROM {$this->t_prefix}rejections
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$rejections = array();
		while ($row = $query->fetch()) {
			$rejections[$row['rejected_user_id']] = $row['rejected_user_id'];
		}
		$query->closeCursor();	
		$user->rejections = $rejections;	
		
		return $user;
		
	}
	
	public function update_user(GeneralUser $user) {
		$updated = $this->get_user_by_id($user->user_id);
		$user->update($updated->get_data());
	}
	
	public function get_all_users() {
		$users = array();
		
		$query = $this->link->prepare("
				SELECT user_id
				FROM {$this->t_prefix}general_users
				WHERE admin=FALSE
		");
		$query->execute();
		while ($row = $query->fetch()) {
			$users[] = $this->get_user_by_id($row['user_id']);
		}
		$query->closeCursor();		
		
		return $users;
	}
	
	public function get_all_newsletter_addresses() {
		$addresses = array();
		
		$query = $this->link->prepare("
				SELECT email
				FROM {$this->t_prefix}general_users
				WHERE newsletter=TRUE
		");
		$query->execute();
		while ($row = $query->fetch()) {
			$addresses[] = $row['email'];
		}
		$query->closeCursor();		
		
		return $addresses;
	}
	
	// Note: doesn't save rejections
	public function save_user(GeneralUser $user) {
		
		$query = $this->link->prepare("
				UPDATE {$this->t_prefix}general_users
				SET password=?,
					first_name=?,
					last_name=?,
					newsletter=?
				WHERE user_id=?
				LIMIT 1
		");
		$success = $query->execute(array($user->password, $user->first_name, $user->last_name, $user->newsletter, $user->user_id));
		$query->closeCursor();	
		if (!$success) {
			echo "A database error occured. Sorry!";
			if (DEBUG) {
				echo $query->errorInfo();
			}
			die();
		}
		
		if ($user instanceof User) {
		
			$query = $this->link->prepare("
					UPDATE {$this->t_prefix}users
					SET date_of_birth=?,
						gender=?,
						facebook=?,
						about_yourself=?,
						email_when_new_match=?,
						invisible=?,
						blocked=?
					WHERE user_id=?
					LIMIT 1
			");
			$success = $query->execute(array($user->date_of_birth->getDate(), $user->gender, $user->facebook, $user->about_yourself,
								  $user->email_when_new_match, $user->invisible, $user->blocked, $user->user_id));
			$query->closeCursor();		
			if (!$success) {
				echo "A database error occured. Sorry!\n\n";
				if (DEBUG) {
					echo $query->errorInfo();
				}
				die();
			}
			
			$this->save_languages($user);
			
		}
	}
	
	private function save_languages(GeneralUser $user) {		
		
		// Delete all known languages of this user
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}known_languages
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$query->closeCursor();	
		
		// Insert all (new) known languages
		if (count($user->known_languages)) {
			$sql = "
				INSERT INTO {$this->t_prefix}known_languages (
					user_id , language_code )
				VALUES 
					";
			$sql .= $this->repeat_and_join("(?, ?)", count($user->known_languages), ', ');
			$sql_data = array(); 
			for ($index = 0; $index < count($user->known_languages); $index++) {
				$sql_data[] = $user->user_id; 
				$sql_data[] = $user->known_languages[$index];
			}
			$query = $this->link->prepare($sql);
			$query->execute($sql_data);
			$query->closeCursor();
		}
		
		
		// Delete all unknown languages of this user
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}unknown_languages
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$query->closeCursor();	
		
		// Insert all (new) known languages
		if (count($user->unknown_languages_and_levels)) {
			$sql = "
				INSERT INTO {$this->t_prefix}unknown_languages (
					user_id , language_code, level )
				VALUES 
					";
			// Add (?, ?, ?) for each language
			$sql .= $this->repeat_and_join("(?, ?, ?)", count($user->unknown_languages_and_levels), ', ');
			// Add the 3 values for each language
			$sql_data = array(); 
			for ($index = 0; $index < count($user->unknown_languages_and_levels); $index++) {
				$sql_data[] = $user->user_id; 
				$sql_data[] = $user->unknown_languages_and_levels[$index][0];
				$sql_data[] = $user->unknown_languages_and_levels[$index][1];
			}
			$query = $this->link->prepare($sql);
			$query->execute($sql_data);
			$query->closeCursor();
		}
	}
	
	private function repeat_and_join($what, $amount, $separator) {
		if ($amount === 0) {
			return '';
		}
		return implode($separator, array_fill(0, $amount, $what));
	}
	
	public function flag_login(GeneralUser $user) {
		$query = $this->link->prepare("
				UPDATE {$this->t_prefix}general_users
				SET last_login=CURRENT_TIMESTAMP
				WHERE user_id=?
				LIMIT 1
		");
		$query->execute(array($user->user_id));
		$query->closeCursor();	
	}
	
	public function reject(User $user, $rejected_user_id) {
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}rejections (
				user_id , rejected_user_id )
			VALUES 
				(?, ?)
		");
		$query->execute(array($user->user_id, $rejected_user_id));
		$query->closeCursor();
		// Indirect modification of overloaded property User::$rejections has no effect
		// Therefore workaround
		$rejections = $user->rejections;
		$rejections[$rejected_user_id] = $rejected_user_id;
		$user->rejections = $rejections;
	}
	
	public function unreject(User $user, $rejected_user_id) {
		$query = $this->link->prepare("
			DELETE
			FROM {$this->t_prefix}rejections 
			WHERE
				user_id=? AND rejected_user_id=?
		");
		$query->execute(array($user->user_id, $rejected_user_id));
		$query->closeCursor();
		// Indirect modification of overloaded property User::$rejections has no effect
		// Therefore workaround
		$rejections = $user->rejections;
		unset($rejections[$rejected_user_id]);
		$user->rejections = $rejections;
	}
	
	public function remove_user(GeneralUser $user) {
		
		if ($user instanceof User) {
			
			// Remove (un)known languages
			$user->known_languages = array();
			$user->unknown_languages_and_levels = array();
			$this->save_languages($user);
			
			// Table rejections
			$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}rejections 
				WHERE
					user_id=? OR rejected_user_id=?
			");
			$query->execute(array($user->user_id, $user->user_id));
			$query->closeCursor();
		
			// Table users
			$query = $this->link->prepare("
					DELETE
					FROM {$this->t_prefix}users
					WHERE user_id=?
			");
			$query->execute(array($user->user_id));
			$query->closeCursor();	
		
			// TODO: what about messages sent log?
			
		}
		
		// Table general_users
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}general_users
				WHERE user_id=?
		");
		$query->execute(array($user->user_id));
		$query->closeCursor();	
		
	}
	
	/**
	 * Creates a challenge and challenge_id.
	 * 
	 * Returns: (challenge_is, challenge)
	 */
	public function create_challenge() {
		$challenge = generate_random_string(20);
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}challenges (
				challenge )
			VALUES (
				? );
		");
		$query->execute(array($challenge));
		$query->closeCursor();
		$challenge_id = $this->link->lastInsertId();	
		return array($challenge_id, $challenge);	
	}
	
	/**
	 * Get the challenge that belongs to a challenge_id. If the challenge_id
	 * is unknown, return null. If found, the challenge is removed.
	 */
	public function get_challenge($challenge_id) {
		$query = $this->link->prepare("
				SELECT challenge
				FROM {$this->t_prefix}challenges
				WHERE challenge_id=?
				LIMIT 0 , 1
		");
		$query->execute(array($challenge_id));
		$row = $query->fetch();
		$query->closeCursor();		
		if ($row) {
			$challenge = $row['challenge'];
			$query = $this->link->prepare("
					DELETE
					FROM {$this->t_prefix}challenges
					WHERE challenge_id=?
					LIMIT 1
			");
			$query->execute(array($challenge_id));
			$query->closeCursor();				
			return $challenge;
		}
		else {
			return null;
		}
	}	
	
	public function log_message_sent(GeneralUser $from, GeneralUser $to) {
		$query = $this->link->prepare("
			INSERT INTO {$this->t_prefix}messages (
				from_user_id, to_user_id )
			VALUES (
				?, ?);
		");
		$query->execute(array($from->user_id, $to->user_id));
		$query->closeCursor();
	}
	
	public function messages_sent_by_user_since(GeneralUser $user, Date $since) {
		$query = $this->link->prepare("
			SELECT COUNT(*)
			FROM {$this->t_prefix}messages
			WHERE from_user_id = ? AND sent_on > ?
		");
		$query->execute(array($user->user_id, $since->getDate()));
		$row = $query->fetch();
		$query->closeCursor();
		return intval($row['COUNT(*)']);
	}
	
	public function messages_sent_since(Date $since) {
		$query = $this->link->prepare("
			SELECT COUNT(*)
			FROM {$this->t_prefix}messages
			WHERE sent_on > ?
		");
		$query->execute(array($since->getDate())); // Produces ISO Format
		$row = $query->fetch();
		$query->closeCursor();
		return intval($row['COUNT(*)']);
	}
	
	public function couples_possible() {
		
		// Create aid view
		$query = $this->link->prepare("
			CREATE VIEW couples(teacher,scolar) AS (
				SELECT {$this->t_prefix}known_languages.user_id, {$this->t_prefix}unknown_languages.user_id
				FROM {$this->t_prefix}known_languages 
					JOIN {$this->t_prefix}unknown_languages 
						ON {$this->t_prefix}known_languages.language_code = {$this->t_prefix}unknown_languages.language_code
				WHERE {$this->t_prefix}known_languages.user_id != {$this->t_prefix}unknown_languages.user_id
			);
		");
		$query->execute();
		$query->closeCursor();
		
		// Do the actual query
		$query = $this->link->prepare("
			SELECT COUNT(*)
			FROM couples JOIN couples AS couples2 
			WHERE couples.teacher=couples2.scolar AND couples.scolar=couples2.teacher;
		");
		// This gives twice the amount of unique couples
		$query->execute();
		$row = $query->fetch();
		$couples = intval($row['COUNT(*)']) / 2;
		$query->closeCursor();
		
		// Remove aid view
		$query = $this->link->prepare("
			DROP VIEW couples;
		");
		$query->execute();
		$query->closeCursor();
		
		return $couples;
	}
	
	/**
	 * Do some database maintenance
	 */
	public function clean() {
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}challenges
				WHERE timestamp < DATE_SUB(NOW(), INTERVAL 1 DAY)
		");
		$query->execute();
		$query->closeCursor();	
		
		$query = $this->link->prepare("
				DELETE
				FROM {$this->t_prefix}signup_users
				WHERE registration_time < DATE_SUB(NOW(), INTERVAL 7 DAY)
		");
		$query->execute();
		$query->closeCursor();				
	}
	
}


/*class DummyLanguageTandemDatabase implements ILanguageTandemDatabase {
	
	public function is_email_known($email) {
		return false;
	} 
	
	public function create_new_signup_user($name, $email) {
		return generate_random_string(26);
	}
	
	public function signup_secret_exists($secret) {
		return true;
	}
	
	public function get_signup_user_data($secret) {
		return array('name' => 'Pieter-Jan', 'email'=>'pj.dewitte@gmail.com');		
	}
	
	public function remove_signup_user($secret) {
	}
	
	public function create_login_by_url_secret($user) {
		return 'ekwehfkuehf';
	}
	
	public function get_login_by_url_user($secret) {
		return $this->get_user_by_id(null);
	}
	
	public function flag_login($user) {
	}

	public function create_user($user_data) {
		return get_user_by_id(null);
	}
	
	public function get_user_by_id($user_id) {
		return $this->get_user_by_email(null);
	}
	
	public function get_user_by_email($email) {
		return new User(array(
			'user_id' => 0,
			'email' =>	'pj.dewitte@gmail.com',
			'password' => 'a969939eba97266f2575bc75d8fcdea8ad74684a',
			'first_name' => 'Pieter-Jan',
			'last_name' => 'Dewitte',
			'admin' => true,
			'newsletter' => true,
			'date_of_birth' => new Date(),
			'gender' => 'M',
			'facebook' => '',
			'about_yourself' => 'I made this website',
			'email_when_new_match' => true,
			'newsletter' => false,
			'signup_date' => new Date(),
			'blocked' => false,
			'known_languages' => array('en', 'nl'),
			'unknown_languages_and_levels' => array(array('ar', 10)),
			'rejections' => array(),
			'last_login' => new Date()
		));		
	}
	
	public function get_all_users() {
		return array($this->get_user_by_id(null));
	}
	
	public function get_all_newsletter_addresses() {
		return array($this->get_user_by_id(null)->email);
	}
	
	public function save_user($user) {}
	
	public function update_user($user) {
		return $user;		
	}
	
	public function reject($user, $rejected_user_id) {}
	public function unreject($user, $rejected_user_id) {}
	
	public function remove_user($user) {}
	
	public function create_challenge() {
		$challenge = 'This is like a random string';
		$challenge_id = 1;	
		return array($challenge_id, $challenge);	
	}
	
	public function get_challenge($challenge_id) {
		return 'This is like a random string';
	}	
	
	public function log_message_sent($from, $to) {}
	
	public function messages_sent_by_user_since($user, $since) {
		return 0;
	}
	
	public function messages_sent_since($since) {
		return 0;
	}
	
}*/


class GeneralUser extends Entity {
    
    // INTERNAL
    const user_id = 'user_id';
    
	const email = 'email';
	const password = 'password'; //  sha1
    const first_name = 'first_name';
	const last_name = 'last_name';
	const admin = 'admin';
    const newsletter = 'newsletter';
    const last_login = 'last_login';
	
}


class Admin extends GeneralUser {
	
	public function __construct($data) {
    	parent::__construct($data);
    	$this->admin = true;
	}
	
}


class User extends GeneralUser {
    
	const date_of_birth = 'date_of_birth';
	const gender = 'gender'; // M,V
	const facebook = 'facebook';
	const about_yourself = 'about_yourself';
	const known_languages = 'known_languages';
	const email_when_new_match = 'email_when_new_match';
	const invisible = 'invisible';
	
	const unknown_languages_and_levels = 'unknown_languages_and_levels';
	//const partner_min_age = 'partner_min_age';
	//const partner_max_age = 'partner_max_age';
	//const partner_gender = 'partner_gender'; // (M,F,B)
	const rejections = 'rejections';

    const signup_date = 'signup_date';
    const blocked = 'blocked';
	
	public function __construct($data) {
    	parent::__construct($data);
    	$this->admin = false;
	}
	
	public function get_profile_img_url() {
		if (! $this->facebook) {
			return '';
		}
		// drop http://www.facebook.com/
		$facebook_user = substr($this->facebook, 24);
		return 'http://graph.facebook.com/'.$facebook_user.'/picture';
	}
	
	public function calculate_age() {
		$now = new Date();
		return floor(($now->dateDiff($this->date_of_birth) + 1) / 365.25);
	}
	
	public function get_known_languages_str() {
		$readable = array();
		foreach ($this->known_languages as $code) {
			$readable[] = LanguageCodeInput::get_english_language_name($code);
		}
		return implode(', ', $readable);
	}
	
	public function get_unknown_languages_str() {
		$readable = array();
		foreach ($this->unknown_languages_and_levels as $item) {
			$language = LanguageCodeInput::get_english_language_name($item[0]);
			$level =  strtolower(LevelInput::$levels[$item[1]]);
			$readable[] = "$language (now $level)";
		}
		return implode(', ', $readable);
	}
	
}